package com.tengju.bff.interfaces.app.user.facade;

import com.tengju.bff.interfaces.app.user.assembler.UserInfoAssembler;
import com.tengju.bff.interfaces.app.user.vo.UserInfoVO;
import com.tengju.bff.interfaces.app.user.vo.UserStarSuperiorSecVO;
import com.tengju.user.domain.model.user.StarLevelEnum;
import com.tengju.user.domain.model.user.UserIdCode;
import com.tengju.user.domain.model.user.UserInfo;
import com.tengju.user.domain.model.user.UserInfoRepository;
import com.tengju.user.domain.service.RemoteUserService;
import com.tengju.user.domain.service.UserDocService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author chenhang
 * @Date 2021/1/6
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class StarInfoFacade {

    private final UserDocService userDocService;
    private final UserInfoRepository userInfoRepository;
    private final RemoteUserService remoteUserService;

    public UserStarSuperiorSecVO getSuperiorSec(Long idCode) {
        UserStarSuperiorSecVO userStarSuperiorSecVO = new UserStarSuperiorSecVO();
        userStarSuperiorSecVO.setIdCode(idCode);

        //查询用户信息
        UserInfo userInfo = userInfoRepository.getByIdCode(UserIdCode.of(idCode));
        if (userInfo != null) {
            userStarSuperiorSecVO.setStarLevel(userInfo.getStarLevel());
        } else {
            userStarSuperiorSecVO.setStarLevel(StarLevelEnum.NONE.getCode());
        }

        //查询所属sec信息
        UserInfo superiorUserInfo = findSuperiorUser(idCode, StarLevelEnum.SEC, new HashSet<>());
        if (superiorUserInfo != null) {
            userStarSuperiorSecVO.setSuperiorSecIdCode(superiorUserInfo.getIdCode().getValue());
            userStarSuperiorSecVO.setSuperiorSecNickName(superiorUserInfo.getNickName());
        }
        return userStarSuperiorSecVO;
    }

    private UserInfo findSuperiorUser(Long idCode, StarLevelEnum starLevel, Set<Long> resolved) {
        if (idCode == null || starLevel == null) {
            return null;
        }
        if (resolved == null) {
            resolved = new HashSet<>();
        }
        if (resolved.contains(idCode)) {
            log.error("上级寻找发现环路：{}",idCode);
            return null;
        }
        UserInfo userInfo = userDocService.searchUserByIdCodeOrMobile(UserIdCode.of(idCode), null);
        if (userInfo == null) {
            return null;
        }
        if (starLevel.getCode().equals(userInfo.getStarLevel())) {
            return userInfo;
        }
        if (userInfo.getPidCode() == null) {
            return null;
        }
        resolved.add(idCode);
        return findSuperiorUser(userInfo.getPidCode().getValue(),starLevel,resolved);
    }


    public List<UserInfoVO> listSec(Integer pageNo, Integer pageSize) {
        Integer offset = Math.max(((pageNo - 1) * pageSize),0);
        List<UserInfo> userInfoList = userInfoRepository.listByStarLevel(StarLevelEnum.SEC, offset, pageSize);
        List<UserIdCode> idCodes = userInfoList.stream()
                .map(v -> v.getIdCode())
                .distinct()
                .collect(Collectors.toList());
        List<UserInfo> externalUserInfos = remoteUserService.getByIdList(idCodes);
        Map<Long, UserInfo> externalUserInfoMap = externalUserInfos.stream()
                .collect(Collectors.toMap(k -> k.getIdCode().getValue(), v -> v, (v1, v2) -> v1));
        return userInfoList.stream()
                .map(v -> {
                    Long idCode = v.getIdCode().getValue();
                    UserInfo externalUserInfo = externalUserInfoMap.get(idCode);
                    v.completeInfo(externalUserInfo.getMobile(),
                            externalUserInfo.getName(),
                            externalUserInfo.getNickName(),
                            externalUserInfo.getPidCode());
                    return UserInfoAssembler.userToVO(v);
                })
                .collect(Collectors.toList());
    }
}
